#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Mikan WSGI Module

Mikan Python Web Framework
"""

__author__ = "K.Sonohara"
__status__ = "develop"
__version__ = "0.0.0_36"
__date__    = "2014/01/05"
__license__ = 'LGPL'

# ------------------------------------------------------------
## インポート
# ------------------------------------------------------------
# Ptyhon
import os
import cgi
import traceback

# WSGI
from wsgiref.util import setup_testing_defaults

# beaker
try:
	from beaker.middleware import SessionMiddleware
	session = True
except:
	session = False

# ESiPC
from esipc import ESiPCProperty

# Mikan
from mikan.core import MIKAN_HTTP_HEADER, MIKAN_INI, MIKAN_HTTP_STATUS
from mikan.exception import AbstractMikanException, AbstractMikanStatusException, MikanStatusException
from mikan.app.errorapp import MikanHTMLErrorApp
from mikan.webapp import MikanWebapp
from mikan.request import MikanRequest

# ------------------------------------------------------------
## 変数
# ------------------------------------------------------------

# ------------------------------------------------------------
## 関数
# ------------------------------------------------------------

# ------------------------------------------------------------
## クラス
# ------------------------------------------------------------

# ------------------------------------------------------------
## Mikan WSGI リクエストクラス
#
class MikanWSGIRequest(MikanRequest):

	# ----------------------------------------------------
	## コンストラクタ
	#  @param webapp Webapp情報
	#  @param environ リクエスト情報
	def __init__(self, webapp, environ):
		# 値の設定
		self.FEnviron = environ
		self.FWSGI = True
		self.FFieldStorage = None

		# 継承元処理
		super(MikanWSGIRequest, self).__init__(webapp)



	# ----------------------------------------------------
	## 環境変数 フィールドゲッター
	# @return 取得した値
	def get_environ(self):
		return self.FEnviron

	# ----------------------------------------------------
	## WSGI処理化どうか フィールドゲッター
	# @return 取得した値(TrueならWSGI処理)
	def is_wsgi(self):
		return self.FWSGI

	# ----------------------------------------------------
	## HTTPコンテンツ WSGI結果
	# @return 取得した値
	def wsgi_content(self):
		return self.FContent

	# ----------------------------------------------------
	## WSGI用URL フィールドゲッター
	# @return 取得した値
	def get_wsgi_url(self):
		try:
			return self.get_config_value(MIKAN_INI.MIKAN, MIKAN_INI.WSGI_URL)
		except:
			return ""

	def get_wsgi_path(self):
		return self.get_config_value(MIKAN_INI.MIKAN, MIKAN_INI.WSGI_PATH)

	def get_real_path(self):
		w = self.wsgipath
		if w != "":
			u = self.get_path_info()
			if u.startswith(w):
				return u[len(w):len(u)]
			
		return self.get_path_info()

	# ----------------------------------------------------
	## HTTPヘッダー WSGI結果
	# @return 取得した値
	def wsgi_headers(self):
		h = self.headers
		h[MIKAN_HTTP_HEADER.NAME_CONTENT_LENGTH] = str(self.contentlength)

		return self.headers.items()

	# ----------------------------------------------------
	## HTTPコード WSGI結果
	# @return 取得した値
	def wsgi_status(self):
		return  "%d %s" % (self.status, MIKAN_HTTP_STATUS.CODES[self.status])

	# ----------------------------------------------------
	## フィールドストレージ フィールドゲッター
	# @return 取得した値
	def get_field_storage(self):
		if self.FFieldStorage == None:
			try:
				if (self.isgetmethod):
					self.FFieldStorage = cgi.FieldStorage(environ=self.environ, fp=self.environ.get('QUERY_STRING'))

				elif (self.ispostmethod):
					self.FFieldStorage = cgi.FieldStorage(environ=self.environ, fp=self.environ['wsgi.input'])
			except:
				pass

		return self.FFieldStorage

	# ----------------------------------------------------
	## Property
	iswsgi = ESiPCProperty(is_wsgi, None, None)
	wsgiurl = ESiPCProperty(get_wsgi_url, None, None)
	wsgipath = ESiPCProperty(get_wsgi_path, None, None)

# ------------------------------------------------------------
## Mikan WSGI アプリケーションクラス
#
class MikanWSGIWebapp(MikanWebapp):

	# ----------------------------------------------------
	## コンストラクタ
	#  @param reloading リロード処理するかどうか
	#  @param mikan_root MIKAN_ROOT
	#  @param mikan_config MIKAN_CONFIG
	def __init__(self, reloading=False, mikan_root=os.path.dirname(__file__) + '/..', mikan_config=os.path.dirname(__file__) + '/../etc'):
		# 継承元処理
		super(MikanWSGIWebapp, self).__init__(reloading, mikan_root, mikan_config)

	# ----------------------------------------------------
	## リクエスト作成
	#  @param environ WSGI環境変数
	def request(self, environ):
		# ログ
		if self.islogdebug:
			self.logger.debug(environ)

		# 再読み込み
#		if (self.isreload):
#			reload(viewlet)
#			reload(view)

		# リクエスト作成
		return MikanWSGIRequest(self, environ)

	# ----------------------------------------------------
	## 処理
	#  @param environ WSGI環境変数
	#  @param start_response 処理結果
	#  @return 処理結果
	def __call__(self, environ, start_response):
		# 変数
		r = None
		rc = None

		# ログ
		if self.islogdebug:
			self.logger.debug("WSGI")

		try:
			# 初期化
			setup_testing_defaults(environ)

			try:
				# リクエスト作成
				r = self.request(environ)

				# 処理
				a = self.perform(r)

				# 処理無し
				if (a == None):
					raise MikanStatusException(r, 404)

				# ログ
				if self.islogdebug:
					self.logger.debug(a)
			except Exception, e:
				# ログ
				if self.islogdebug:
					self.logger.debug(traceback.format_exc())
					self.logger.debug(e)

				# エラー表示
				MikanHTMLErrorApp(r, exception=e)

			# ログ
			if self.islogdebug:
				self.logger.debug(r.wsgi_status())
				self.logger.debug(r.wsgi_headers())

			# 処理ステータス・ヘッダー
			start_response(r.wsgi_status(), r.wsgi_headers())

			# 結果
			rc = r.wsgi_content()
		finally:
			try:
				# 破棄
				if r:
					r.destroy()
			except:
				pass

		# 結果
		return rc

	def invoke(self):
		if session:
			return SessionMiddleware(self, config=dict(self.config.items("session")))
		else:
			return self

# ------------------------------------------------------------
## メイン関数
# ------------------------------------------------------------
if __name__ == '__main__':
	pass

# ------------------------------------------------------------
